﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class BossBattleScript : MonoBehaviour {
    public GameObject playerParty, enemyParty;
    private List<BossCombatant> combatants = new List<BossCombatant>();
    private GameObject canvas;

    private BattleStage state = BattleStage.PICKACTION;
    private int turn = 0;

    void OnGUI()
    {
        foreach(BossCombatant combatant in combatants)
        {
            string text = combatant.gObject.name + "\nHealth: " + combatant.health + "/" + combatant.maxHealth;
            GUI.skin.label.alignment = TextAnchor.MiddleCenter;
            Vector3 position = Camera.main.WorldToScreenPoint(combatant.gObject.transform.position);
            Vector3 textSize = GUI.skin.label.CalcSize(new GUIContent(text));
            GUI.Label(new Rect(position.x - (textSize.x / 2), Screen.height - (position.y - 30), textSize.x, textSize.y), text);
        }
    }

    // Use this for initialization
    void Start () {
        canvas = GameObject.Find("Canvas");
		foreach (Transform child in playerParty.transform)
        {
            combatants.Add(new BossCombatant(child.gameObject, 100, CombatantType.PLAYER));
        }
        foreach (Transform child in enemyParty.transform)
        {
            combatants.Add(new BossCombatant(child.gameObject, 100, CombatantType.ENEMY));
        }
	}
	
	// Update is called once per frame
	void Update () {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Flee();
        }

        if (turn >= combatants.Count)
        {
            turn = 0;
        }
        foreach (BossCombatant combatant in combatants)
        {
            if (combatant.type == CombatantType.PLAYER)
            {
                BetterFind(combatant.gObject, "TurnArrow").SetActive(false);
            }
        }
        if (combatants[turn].type == CombatantType.PLAYER)
        {
            BetterFind(combatants[turn].gObject, "TurnArrow").SetActive(true);
        }

		switch (state)
        {
            case BattleStage.PICKACTION:
                if (combatants[turn].type == CombatantType.ENEMY)
                {
                    List<BossCombatant> players = new List<BossCombatant>();
                    foreach(BossCombatant combatant in combatants)
                    {
                        if (combatant.type == CombatantType.PLAYER) players.Add(combatant);
                    }
                    BossCombatant chosenPlayer = players[Random.Range(0, players.Count)];
                    int damageDone = Random.Range(5, 45);
                    if (PlayerInventory.equippedOutfit != null)
                    {
                        int blockRandom = Random.Range(0, 49);
                        if (PlayerInventory.equippedOutfit.armor >= blockRandom)
                        {
                            Debug.Log("All damage blocked! Armor is " + PlayerInventory.equippedOutfit.armor + ", blockRandom is " + blockRandom);
                            damageDone = 0;
                        } else
                        {
                            Debug.Log("Damage not blocked! Armor is " + PlayerInventory.equippedOutfit.armor + ", blockRandom is " + blockRandom);
                        }
                    }
                    chosenPlayer.health -= damageDone;
                    BetterFind(combatants[turn].gObject, "LineRender").SetActive(true);
                    BetterFind(combatants[turn].gObject, "LineRender").GetComponent<LineRenderer>().SetPosition(0, combatants[turn].gObject.transform.position);
                    BetterFind(combatants[turn].gObject, "LineRender").GetComponent<LineRenderer>().SetPosition(1, combatants[turn].gObject.transform.position + Vector3.up * 0.1f);
                    StartCoroutine(AnimateLine(BetterFind(combatants[turn].gObject, "LineRender"), chosenPlayer));
                    state = BattleStage.PROGRESSING;
                }
                break;
            case BattleStage.PICKTARGET:
                int enemiesCount = 0;
                foreach (BossCombatant combatant in combatants)
                {
                    if (combatant.type == CombatantType.ENEMY) enemiesCount++;
                }

                BetterFind(canvas, "ActionButtons").SetActive(false);
                BetterFind(canvas, "ActionText").SetActive(true);
                BetterFind(canvas, "ActionText").GetComponent<Text>().text = "Choose an enemy to attack";

                foreach (BossCombatant combatant in combatants)
                {
                    if (combatant.type == CombatantType.ENEMY)
                    {
                        BetterFind(combatant.gObject, "ActionArrow").SetActive(true);
                    }
                }

                if (Input.GetMouseButtonDown(0))
                {
                    RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
                    if (hit.collider != null)
                    {
                        foreach (BossCombatant combatant in combatants)
                        {
                            if (combatant.type == CombatantType.ENEMY && hit.collider.gameObject == combatant.gObject)
                            {
                                int damageDone = Random.Range(0, 35);
                                if (PlayerInventory.equippedWeapon != null) damageDone += PlayerInventory.equippedWeapon.damage;
                                combatant.health -= damageDone;
                                BetterFind(combatants[turn].gObject, "LineRender").SetActive(true);
                                BetterFind(combatants[turn].gObject, "LineRender").GetComponent<LineRenderer>().SetPosition(0, combatants[turn].gObject.transform.position);
                                BetterFind(combatants[turn].gObject, "LineRender").GetComponent<LineRenderer>().SetPosition(1, combatants[turn].gObject.transform.position + Vector3.up * 0.1f);
                                StartCoroutine(AnimateLine(BetterFind(combatants[turn].gObject, "LineRender"), combatant));
                                state = BattleStage.PROGRESSING;
                            }
                        }
                    }
                }
                break;
            case BattleStage.PROGRESSING:
                BetterFind(canvas, "ActionButtons").SetActive(true);
                BetterFind(canvas, "ActionText").SetActive(false);

                foreach (BossCombatant combatant in combatants)
                {
                    BetterFind(combatant.gObject, "ActionArrow").SetActive(false);
                }

                List<BossCombatant> toRemove = new List<BossCombatant>();
                foreach(BossCombatant combatant in combatants)
                {
                    if (combatant.health <= 0)
                    {
                        toRemove.Add(combatant);
                    }
                }
                foreach(BossCombatant removable in toRemove)
                {
                    Destroy(removable.gObject);
                    combatants.Remove(removable);
                }

                state = BattleStage.ENDOFTURN;
                break;
            case BattleStage.ENDOFTURN:
                int playerCount = 0, enemyCount = 0;
                foreach(BossCombatant combatant in combatants)
                {
                    if (combatant.type == CombatantType.PLAYER) playerCount++;
                    else if (combatant.type == CombatantType.ENEMY) enemyCount++;
                }

                if (playerCount == 0 || enemyCount == 0)
                {
                    if (playerCount == 0)
                    {
                        state = BattleStage.LOSS;
                    }
                    else if (enemyCount == 0)
                    {
                        state = BattleStage.VICTORY;
                    }
                }
                else
                {
                    turn++;
                    if (turn >= combatants.Count)
                    {
                        turn = 0;
                    }
                    state = BattleStage.PICKACTION;
                }
                break;
            case BattleStage.VICTORY:
            case BattleStage.LOSS:
                BetterFind(canvas, "ActionButtons").SetActive(false);
                if (state == BattleStage.VICTORY)
                {
                    BetterFind(canvas, "VictoryText").SetActive(true);
                }
                else if (state == BattleStage.LOSS)
                {
                    BetterFind(canvas, "LossText").SetActive(true);
                }

                if ((Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) || Input.GetMouseButtonDown(0))
                {
                    if (state == BattleStage.VICTORY) state = BattleStage.LOOTSCREEN;
                    else SceneManager.LoadScene(1);
                }
                break;
            case BattleStage.LOOTSCREEN:
                BetterFind(canvas, "VictoryText").SetActive(false);
                BetterFind(canvas, "LootPanel").SetActive(true);
                List<CraftMaterialAmount> loot = SingletonManager.GenerateLootList(9);
                string lootText = "";
                foreach (CraftMaterialAmount cma in loot)
                {
                    lootText += cma.amount + "x " + cma.material.name + "\n";
                }
                PlayerInventory.Add(loot);
                BetterFind(BetterFind(canvas, "LootPanel"), "LootText").GetComponent<Text>().text = lootText;
                state = BattleStage.WAIT_FOR_BREAK;
                break;
            case BattleStage.WAIT_FOR_BREAK:
                if ((Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) || Input.GetMouseButtonDown(0))
                {
                    SceneManager.LoadScene(1);
                }
                break;
        } 
	}

    public GameObject BetterFind(GameObject parent, string name)
    {
        Transform[] trs = parent.GetComponentsInChildren<Transform>(true);
        foreach (Transform t in trs)
        {
            if (t.name == name) return t.gameObject;
        }
        return null;
    }

    IEnumerator AnimateLine(GameObject LineRender, BossCombatant target)
    {
        yield return new WaitForSeconds(0.5f);
        if (target.gObject != null) LineRender.GetComponent<LineRenderer>().SetPosition(1, target.gObject.transform.position);
        StartCoroutine(RemoveLine(LineRender));
    }

    IEnumerator RemoveLine(GameObject LineRender)
    {
        yield return new WaitForSeconds(1);
        LineRender.SetActive(false);
    }

    public void Attack()
    {
        state = BattleStage.PICKTARGET;
    }

    public void SkipTurn()
    {
        state = BattleStage.PROGRESSING;
    }

    public void Skill()
    {
        state = BattleStage.VICTORY;
    }

    public void Flee()
    {
        BetterFind(canvas, "FleePanel").SetActive(true);
    }

    public void ConfirmFlee()
    {
        SceneManager.LoadScene(1);
    }

    public void CancelFlee()
    {
        BetterFind(canvas, "FleePanel").SetActive(false);
    }
}

internal class BossCombatant
{
    public GameObject gObject;
    public int health, maxHealth;
    public CombatantType type;

    public BossCombatant(GameObject p_gObject, int p_health, CombatantType p_type)
    {
        gObject = p_gObject;
        health = p_health;
        maxHealth = p_health;
        type = p_type;
    }
}

enum CombatantType { PLAYER, ENEMY };
enum BattleStage { PICKACTION, PICKTARGET, PROGRESSING, ENDOFTURN, VICTORY, LOSS, LOOTSCREEN, WAIT_FOR_BREAK };